/**
 * author: zhou
 * date: 2017.10.18
 * description: 自定义中间件文件
 * middlewares: {
 *      logger: 日志记录
 *      isRequestBodyComplete: 验证请求体是否完整
 *      authGuard: 验证用户请求是否合法
 * }
 */

// 引入模块
const   crypto       = require('crypto'),
        { md5key }   = require('config-lite')(__dirname),
        logger       = require('./log'),
        redis        = require('../core/redis/redis'),
        redisPromise = require('../core/redis/redisPromise'),
        mongoPromise = require('../core/mongo/mongoPromise.js'),
        School       = require('../core/mongo/models/system/schoolModel');

const middlewares = {
    /**
     * 完整日志记录
     * 请求和返回,请求时长
     * @param {*} ctx 
     * @param {*} next 
     */
    async logger(ctx, next) {
        const startTime = new Date();
        let ms = 0;
        try {
            logger.logRequest(ctx, startTime);
            await next();
            ms = new Date() - startTime;
            logger.logResponse(ctx, ms);
        } catch (error) {
            ms = new Date() - startTime;
            logger.logError(error, ms);
        }
    },
    /**
     * 验证请求体是否完整
     * @param {*} ctx 
     * @param {*} next 
     */
    async isRequestBodyComplete(ctx, next) {
        let body = ctx.request.body;
        if (body && body.body && typeof body.body === 'object' && body.body.hmac) {
            const hmac = body.body.hmac;
            delete body.body.hmac;
            const newHmac = crypto.createHash('md5')
                                .update(JSON.stringify(body.body) + JSON.stringify(body.data) + md5key, 'utf8')
                                .digest('hex');
            if (hmac === newHmac) {
                await next();
            } else {
                ctx.body = { success: false, message: '抱歉,请求数据包不完整,请检查', state: 10001 };
            }    
        } else {
            ctx.body = { success: false, message: '抱歉,请求体参数有误,请检查', state: 10002 };
        }
    },
    /**
     * 验证用户请求是否合法
     * @param {*} ctx 
     * @param {*} next 
     */
    async authGuard(ctx, next) {
        let body = ctx.request.body;
        if (body && body.body && typeof body.body === 'object' && body.body.token) {
            // 获取token,查找redis中是否存在
            const token = body.body.token;
            const getPipeline = redis.pipeline().get(`SESSION:${token}`);
            const result = await redisPromise(ctx, getPipeline);
            if (result.length > 0 && result[0][1]) {
                // 如果请求中存在schoolId,查看当前school是否可用
                const { schoolId } = body.data;
                if (schoolId) {
                    const query = School.findById(schoolId);
                    const result = await mongoPromise(ctx, query);
                    if (result) {
                        if (result.status === 1) {
                            await next();
                        } else if (result.status === 2) {
                            ctx.body = { success: false, message: '抱歉,您所在学校已被禁用,请联系系统管理员', state: 10007 };
                        } else {
                            ctx.body = { success: false, message: '抱歉,您所在学校已被删除,请联系系统管理员', state: 10007 };
                        }
                    } else {
                        ctx.body = { success: false, message: '抱歉,您所在学校不存在,请联系系统管理员', state: 10007 };
                    }
                } else {
                    await next();
                }
            } else {
                ctx.body = { success: false, message: '抱歉,登录已过期,请重新登录', state: 10006 };
            }
        } else {
            ctx.body = { success: false, message: '抱歉,非法请求,请联系管理员', state: 10002 };
        }
    }
};

module.exports = middlewares;